Skip to content

Normalize the axis in UnitQuaternion.AngVec - #266

Open
wpyaoxueros wants to merge 2 commits into
rai-opensource:masterfrom
wpyaoxueros:codex/fix-angvec-axis-normalization
Open

wpyaoxueros wants to merge 2 commits into
rai-opensource:masterfrom
wpyaoxueros:codex/fix-angvec-axis-normalization

Conversation

@wpyaoxueros

@wpyaoxueros wpyaoxueros commented Oct 17, 2026 •

Copy link
Copy Markdown

UnitQuaternion.AngVec(0.5, [1, 2, 3]) currently produces a quaternion with norm greater than one and a matrix that is not the requested rotation. Normalize the axis before constructing a nonzero-angle quaternion, while returning the identity for angles considered zero by smb.iszero() after unit conversion.

Away from that zero-angle tolerance, a zero axis raises ValueError. The base functions (angvec2r, angvec2tr and SO3.AngleAxis) currently return the identity for a zero axis, even for a nonzero angle; this PR does not change them. The earlier description incorrectly claimed consistency with those base constructors. Their alignment is separate, as discussed in review.

Regression coverage includes norm, angle/axis round-trip, matrix agreement, degrees, unit-axis controls, exact and near-zero angles in both units, and positive/negative small angles outside the tolerance. These controls preserve nonzero rotation with a valid axis and reject a zero axis outside the tolerance.

Validation on the designated Linux workstation, Python 3.11:

  • Original normalization regressions against unchanged master: 5 failed, 3 passed; original fix: 8 passed.
  • Follow-up tests against the previous PR head 54fb3c8: four near-zero subtest failures; the four other new control subtests passed.
  • Final focused tests: 12 passed, 8 subtests passed.
  • Full suite: 414 passed, 11 skipped, 63 subtests passed (15 warnings).
  • Project-pinned Black 23.10.0 and whitespace checks passed. All execution and formatting ran on the remote workstation.

AI assistance: an AI coding agent helped investigate, implement, test, and review this change. No independent human review is claimed.

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@petercorke

Copy link
Copy Markdown
Collaborator

Thanks very much for the report and the fix, @wpyaoxueros. I've confirmed the bug: on master UnitQuaternion.AngVec(0.5, [1, 2, 3]) returns a quaternion with norm ≈ 1.34, because the axis isn't normalized and the constructor is called with norm=False, check=False. The change and the regression tests look good to me.

Two small things, neither blocking:

  1. Exact zero test. if theta == 0: is an exact float comparison, whereas the rest of the library uses a tolerance, e.g. spatialmath.base.iszero(theta) (tolerance in units of eps, as used by unitvec and iszerovec). With the exact test, an angle like 1e-20 with a zero axis raises ValueError, while 0 returns the identity. Using smb.iszero(theta) would make that boundary consistent with the rest of the package.
  2. Description. The new ValueError for a nonzero angle with a zero axis is not consistent with the base angle-axis functions: angvec2r(0.5, [0, 0, 0]) (and so SO3.AngleAxis, angvec2tr etc.) currently returns the identity silently, whatever the angle. I think the new AngVec behaviour is the better one, so no change is needed here. I'll open a separate PR to align the base functions with it.

@wpyaoxueros

Copy link
Copy Markdown
Author

Thanks for confirming the bug and for both suggestions. I've updated AngVec to use smb.iszero(theta) after converting the angle to radians, and clarified the method's note. Added positive/negative near-zero cases in radians and degrees, plus controls ensuring a small angle outside the tolerance still produces its rotation with a valid axis and raises for a zero axis.

The four near-zero subtests fail on the previous PR head and pass with the update. Remote validation: focused tests 12 passed plus 8 subtests; full suite 414 passed, 11 skipped plus 63 subtests. Black 23.10.0 and whitespace checks pass.

You're also right about the description: the base angle-axis functions currently return the identity for a zero axis, including at a nonzero angle. I've corrected the PR text and left those functions unchanged for your separate alignment work.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants